/*    file: main.cpp
 *    desc:
 * 
 * created: 2016-04-06
 *  author: chuanjiang.zh@qq.com
 * company: 
 */

#include <stdio.h>
#include <iostream>

#include "BasicType.h"
#include "SharedPtr.h"
#include "TFileUtil.h"
#include "TByteBuffer.h"
#include "BasicMacro.h"
#include "TStringUtil.h"
#include <assert.h>
#include <errno.h>
#include "MediaWriter.h"
#include "DateTime.h"
#include "FfmpegMediaReader.h"


class Application 
{
public:
	Application()
	{
		av::MediaWriterFactory::startup();
	}

	~Application()
	{
		av::MediaWriterFactory::cleanup();
	}

};

typedef std::shared_ptr< av::MediaWriter >	MediaWriterPtr;


class LoopReader
{
public:
	LoopReader():
		m_width(),
		m_height(),
		m_fps(),
		m_codec(),
		m_channels(),
		m_sampleRate(),
		m_acodec()
	{

	}

	~LoopReader()
	{
		close();
	}

	int open(const char* url)
	{
		m_reader.reset(new FfmpegMediaReader());
		int rc = m_reader->open(url);
		if (rc == 0)
		{
			m_width = m_reader->m_width;
			m_height = m_reader->m_height;
			m_fps = m_reader->m_fps;
			m_codec = m_reader->m_codec;
			m_prop = m_reader->m_prop;

			m_channels = m_reader->m_channels;
			m_sampleRate = m_reader->m_sampleRate;
			m_acodec = m_reader->m_acodec;
			m_config = m_reader->m_config;

			m_url = url;

			memset(m_ptsOffset, 0, sizeof(m_ptsOffset));
			memset(m_ptsLast, 0, sizeof(m_ptsLast));
			
		}
		return rc;
	}

	void close()
	{
		if (m_reader)
		{
			m_reader->close();
			m_reader.reset();
		}
	}

	int read(AVPacket& pkt)
	{
		int rc = doRead(pkt);
		if (rc != 0)
		{
			memcpy(m_ptsOffset, m_ptsLast, sizeof(m_ptsOffset));

			m_reader.reset(new FfmpegMediaReader());
			m_reader->open(m_url.c_str());
			rc = doRead(pkt);
		}
		return rc;
	}

	int doRead(AVPacket& pkt)
	{
		int rc = m_reader->read(pkt);
		if (rc == 0)
		{
			if (pkt.dts == AV_NOPTS_VALUE)
			{
				pkt.dts = 1;
				pkt.pts = 1;
			}

			pkt.dts += m_ptsOffset[pkt.stream_index];
			pkt.pts = pkt.dts;

			m_ptsLast[pkt.stream_index] = pkt.dts;
		}
		return rc;
	}

	static bool isVideo(AVPacket& pkt)
	{
		return FfmpegMediaReader::isVideo(pkt);
	}

	int	m_width;
	int m_height;
	int m_fps;
	AVCodecID	m_codec;
	std::string	m_prop;

	int m_channels;
	int m_sampleRate;
	AVCodecID	m_acodec;
	std::string	m_config;

	std::string	m_url;

	int64_t	m_ptsOffset[2];
	int64_t	m_ptsLast[2];

protected:
	std::shared_ptr< FfmpegMediaReader >	m_reader;

};


int main(int argc, char** argv)
{
	std::string filename = "rtsp://admin:sjld16301@192.168.3.65/";
	if (argc > 1)
	{
		filename = argv[1];
	}

	Application app;

	LoopReader reader;
	int rc = reader.open(filename.c_str());
	if (rc != 0)
	{
		return rc;
	}


	MFormat fmt;
	memset(&fmt, 0, sizeof(fmt));
	fmt.width = reader.m_width;
	fmt.height = reader.m_height;
	fmt.framerate = reader.m_fps;
	fmt.codec = reader.m_codec;
	fmt.vProp = (uint8_t*)(reader.m_prop.c_str());
	fmt.vPropSize = reader.m_prop.size();
	fmt.clockRate = AV_TIME_BASE;

	fmt.channels = reader.m_channels;
	fmt.sampleRate = reader.m_sampleRate;
	fmt.audioCodec = reader.m_acodec;
	fmt.config = (uint8_t*)(reader.m_config.c_str());
	fmt.configSize = reader.m_config.size();
	fmt.audioRate = AV_TIME_BASE;

	av::MediaFileFormat fileFormat = av::FILE_TS;
	const char* fileExt = av::MediaWriterFactory::getFileExt(fileFormat);

	MediaWriterPtr writer(av::MediaWriterFactory::create(fileFormat),
		av::MediaWriterFactory::destroy);

	writer->setOutputAudioCodec(MCODEC_AAC);

	std::string outPath("out");
	outPath += fileExt;
	writer->open(outPath.c_str(), fmt);

	int count = 1000000;
	while (count > 0)
	{
		count--;

		AVPacket pkt;
		av_init_packet(&pkt);

		rc = reader.read(pkt);
		if (rc != 0)
		{
			break;
		}

		if (reader.isVideo(pkt))
		{
			writer->writeVideo(pkt.data, pkt.size, pkt.dts, pkt.flags);
		}
		else
		{
			writer->writeAudio(pkt.data, pkt.size, pkt.dts, pkt.flags);
		}

		av_packet_unref(&pkt);

		if ((count % 3000) < 0)
		{
			std::string name = comn::StringUtil::format("%d%s", count, fileExt);
			writer->setFile(name.c_str());
		}
	}

	writer->close();

	return 0;
}